﻿#include "pch.h"

std::map<int64_t, std::shared_ptr<TMethodFile>> MethodFileMap;
int64_t nextMethodHandle = 0x0000000001000001; // 通过高位字节01与谱图句柄区分开
std::mutex handleMethodMutex;

// 生成唯一的句柄
int64_t generateMethodHandle()
{
    std::lock_guard<std::mutex> lock(handleMethodMutex);
    return nextMethodHandle++;
}

// 3.5.1、创建方法
int64_t createMethodFile_(const char *szMethodName, bool innerCall)
{
    clear_error();
    CHECK_NULL_POINTER(szMethodName, -1);
    std::shared_ptr<TMethodFile> MethodFile = std::make_shared<TMethodFile>();
    STRING_COPY(szMethodName, MethodFile.get()->Name);
    int64_t nHandle = generateMethodHandle();
    MethodFileMap.insert({nHandle, MethodFile});
    return nHandle;
}
int64_t createMethodFile(const char *szMethodName)
{
    return createMethodFile_(szMethodName, false);
}

// 3.5.2、打开方法
int64_t openMethodFile_(const char *szFileName, bool innerCall)
{
    clear_error();
    CHECK_NULL_POINTER(szFileName, -1);
    if (!std::filesystem::exists(szFileName))
    {
        SET_ERROR_(ERR_CODE_FILE_NOT_EXISTS, ERR_MESSAGE_FILE_NOT_EXISTS, szFileName);
        return -1;
    }
    std::ifstream file(szFileName, std::ios::binary | std::ios::ate);
    if (!file.is_open())
    {
        SET_ERROR_(ERR_CODE_FILE_OPEN_FAILED, ERR_MESSAGE_FILE_OPEN_FAILED, szFileName);
        return -1;
    }

    std::streampos fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    std::unique_ptr<BYTE[]> buffer(new (std::nothrow) BYTE[static_cast<int32_t>(fileSize)]);
    if (!buffer)
    {
        SET_ERROR_(ERR_CODE_MEM_ALLOC_FAILED, ERR_MESSAGE_MEM_ALLOC_FAILED, "buffer");
        file.close();
        return -1;
    }

    file.read(reinterpret_cast<char *>(buffer.get()), fileSize);
    file.close();

    if (file.gcount() != fileSize)
    {
        SET_ERROR_(ERR_CODE_FILE_READ_FAILED, ERR_MESSAGE_FILE_READ_FAILED, szFileName);
        return -1;
    }

    int64_t nHandle = -1;
    std::shared_ptr<TMethodFile> MethodFile = std::make_shared<TMethodFile>();
    try
    {
        bool success = MethodFile.get()->copyFromBuffer(buffer.get(), fileSize);
        if (!success)
        {
            SET_ERROR_(ERR_CODE_FILE_PARSE_FAILED, ERR_MESSAGE_FILE_PARSE_FAILED, szFileName);
            return -1;
        }
        nHandle = generateMethodHandle();
        MethodFileMap.insert({nHandle, MethodFile});
    }
    CATCH_AND_RETURN(-1);
    return nHandle;
}
int64_t openMethodFile(const char *szFileName)
{
    return openMethodFile_(szFileName, false);
}

// 3.5.3、存储方法
bool saveMethodFile_(int64_t nHandle, const char *szFileName, bool innerCall)
{
    clear_error();
    CHECK_METHOD_HANDLE(nHandle, METHOD_HANDLE);
    CHECK_NULL_POINTER(szFileName, false);

    // 获取对应的 TMethodFile 实例
    std::shared_ptr<TMethodFile> &methodFile = MethodFileMap[nHandle];

    // 计算所需的缓冲区大小
    int32_t bufferSize = methodFile.get()->getTotalLength();
    std::vector<unsigned char> buffer(bufferSize);
    try
    {
        // 将 TMethodFile 实例复制到缓冲区
        if (!methodFile.get()->copyToBuffer(buffer.data(), bufferSize))
        {
            SET_ERROR_(ERR_CODE_FILE_OPEN_FAILED, ERR_MESSAGE_FILE_OPEN_FAILED, szFileName);
            return false;
        }

        // 打开文件以二进制写入模式
        std::ofstream file(szFileName, std::ios::binary);
        if (!file.is_open())
        {
            SET_ERROR_(ERR_CODE_FILE_OPEN_FAILED, ERR_MESSAGE_FILE_OPEN_FAILED, szFileName);
            return false;
        }

        // 将缓冲区内容写入文件
        file.write(reinterpret_cast<const char *>(buffer.data()), bufferSize);

        // 关闭文件
        file.close();
    }
    CATCH_AND_RETURN(false);
    return true;
}
bool saveMethodFile(int64_t nHandle, const char *szFileName)
{
    return saveMethodFile_(nHandle, szFileName, false);
}

// 3.5.4、关闭方法
bool closeMethodFile_(int64_t nHandle, bool innerCall)
{
    clear_error();
    CHECK_METHOD_HANDLE(nHandle, METHOD_HANDLE);
    MethodFileMap.erase(nHandle);
    return true;
}
bool closeMethodFile(int64_t nHandle)
{
    return closeMethodFile_(nHandle, false);
}

// 3.5.5、获取方法基础数据
bool getMethodHead_(int64_t nHandle, int32_t nHandleType, TMethodHead *pBuffer, bool innerCall)
{
    clear_error();
    CHECK_METHOD_HANDLE(nHandle, nHandleType);
    CHECK_NULL_POINTER(pBuffer, false);

    // 获取对应的 TMethodFile 实例
    std::shared_ptr<TMethodFile> methodFile;

    if (nHandleType == METHOD_HANDLE)
    {
        methodFile = MethodFileMap[nHandle];
    }
    else
    {
        std::shared_ptr<TOrgFile> &OrgFile = OrgFileMap[nHandle];
        methodFile = OrgFile.get()->Method;
        if (methodFile.get() == nullptr)
        {
            SET_ERROR_(ERR_CODE_ORG_HAS_NOT_METHOD, ERR_MESSAGE_ORG_HAS_NOT_METHOD, nHandle);
            return false;
        }
    }
    *pBuffer = *(TMethodHead *)methodFile.get();
    return true;
}
bool getMethodHead(int64_t nHandle, int32_t nHandleType, TMethodHead *pBuffer)
{
    return getMethodHead_(nHandle, nHandleType, pBuffer, false);
}

// 3.5.6、设置方法基础数据
bool setMethodHead_(int64_t nHandle, int32_t nHandleType, const TMethodHead *pBuffer, bool innerCall)
{
    clear_error();
    CHECK_METHOD_HANDLE(nHandle, nHandleType);
    CHECK_NULL_POINTER(pBuffer, false);

    std::optional<std::shared_ptr<TMethodFile>> methodFile;
    if (nHandleType == METHOD_HANDLE)
    {
        methodFile = MethodFileMap[nHandle];
    }
    else
    {
        std::shared_ptr<TOrgFile> &OrgFile = OrgFileMap[nHandle];
        if (OrgFile.get()->Method.get() == nullptr)
        {
            OrgFile.get()->Method = std::make_unique<TMethodFile>();
        }
        methodFile = OrgFile.get()->Method;
    }
    if (methodFile.has_value())
    {
        TMethodHead oldHeadData = *(TMethodHead *)methodFile->get();
        *(TMethodHead *)methodFile->get() = *pBuffer;
        // 恢复指针相关数据保持一致性。
        methodFile->get()->EventListOffset = oldHeadData.EventListOffset;
        methodFile->get()->EventListCount = oldHeadData.EventListCount;
        methodFile->get()->CompListOffset = oldHeadData.CompListOffset;
        methodFile->get()->CompListCount = oldHeadData.CompListCount;
        methodFile->get()->GroupListOffset = oldHeadData.GroupListOffset;
        methodFile->get()->GroupListCount = oldHeadData.GroupListCount;
        methodFile->get()->SegmentListOffset = oldHeadData.SegmentListOffset;
        methodFile->get()->SegmentListCount = oldHeadData.SegmentListCount;
        methodFile->get()->CalibListOffset = oldHeadData.CalibListOffset;
        methodFile->get()->CalibListCount = oldHeadData.CalibListCount;
        methodFile->get()->CalibResultOffset = oldHeadData.CalibResultOffset;
        methodFile->get()->CalibResultCount = oldHeadData.CalibResultCount;
    }

    return true;
}
bool setMethodHead(int64_t nHandle, int32_t nHandleType, const TMethodHead *pBuffer)
{
    return setMethodHead_(nHandle, nHandleType, pBuffer, false);
}
// 定义通用的GET函数宏
#define DEFINE_METHOD_GET_FUNCTION(funcName, DataType, DataArray, CountArray, ErrCode, ErrMessage)                                       \
    bool funcName##_(int64_t nHandle, int32_t nHandleType, DataType *pBuffer, int32_t nBufferCount, int32_t *pDataCount, bool innerCall) \
    {                                                                                                                                    \
        clear_error();                                                                                                                   \
        CHECK_METHOD_HANDLE(nHandle, nHandleType);                                                                                       \
        CHECK_NULL_POINTER(pDataCount, false);                                                                                           \
        CHECK_NULL_POINTER(pBuffer, false);                                                                                              \
        std::shared_ptr<TMethodFile> methodFile;                                                                                         \
        if (nHandleType == METHOD_HANDLE)                                                                                                \
        {                                                                                                                                \
            methodFile = MethodFileMap[nHandle];                                                                                         \
        }                                                                                                                                \
        else                                                                                                                             \
        {                                                                                                                                \
            std::shared_ptr<TOrgFile> &OrgFile = OrgFileMap[nHandle];                                                                    \
            methodFile = OrgFile.get()->Method;                                                                                          \
        }                                                                                                                                \
        std::shared_ptr<DataType[]> &pArray = methodFile.get()->DataArray;                                                               \
        *pDataCount = methodFile.get()->CountArray;                                                                                      \
        if (nBufferCount < *pDataCount)                                                                                                  \
        {                                                                                                                                \
            SET_ERROR_(ERR_CODE_BUFFER_INSUFFICIENT, ERR_MESSAGE_BUFFER_INSUFFICIENT, "pBuffer",                                         \
                       1L * sizeof(DataType) * nBufferCount, 1L * sizeof(DataType) * *pDataCount);                                       \
            return false;                                                                                                                \
        }                                                                                                                                \
        if (*pDataCount > 0)                                                                                                             \
        {                                                                                                                                \
            if (pArray.get() == nullptr)                                                                                                 \
            {                                                                                                                            \
                SET_ERROR_(ErrCode, ErrMessage, nHandle, nHandleType);                                                                   \
                return false;                                                                                                            \
            }                                                                                                                            \
            std::copy(pArray.get(), pArray.get() + *pDataCount, pBuffer);                                                                \
        }                                                                                                                                \
        return true;                                                                                                                     \
    }                                                                                                                                    \
    bool funcName(int64_t nHandle, int32_t nHandleType, DataType *pBuffer, int32_t nBufferCount, int32_t *pDataCount)                    \
    {                                                                                                                                    \
        return funcName##_(nHandle, nHandleType, pBuffer, nBufferCount, pDataCount, false);                                              \
    }

// 定义通用的SET函数宏
#define DEFINE_METHOD_SET_FUNCTION(funcName, DataType, DataArray, CountArray, MaxCount)                                   \
    bool funcName##_(int64_t nHandle, int32_t nHandleType, const DataType *pBuffer, int32_t nBufferCount, bool innerCall) \
    {                                                                                                                     \
        clear_error();                                                                                                    \
        CHECK_METHOD_HANDLE(nHandle, nHandleType);                                                                        \
        CHECK_NULL_POINTER(pBuffer, false);                                                                               \
        std::shared_ptr<TMethodFile> methodFile;                                                                          \
        if (nHandleType == METHOD_HANDLE)                                                                                 \
        {                                                                                                                 \
            methodFile = MethodFileMap[nHandle];                                                                          \
        }                                                                                                                 \
        else                                                                                                              \
        {                                                                                                                 \
            std::shared_ptr<TOrgFile> &OrgFile = OrgFileMap[nHandle];                                                     \
            methodFile = OrgFile.get()->Method;                                                                           \
            if (methodFile.get() == nullptr)                                                                              \
            {                                                                                                             \
                methodFile = OrgFile.get()->Method = std::make_shared<TMethodFile>();                                     \
            }                                                                                                             \
        }                                                                                                                 \
        if (nBufferCount <= 0 || nBufferCount > MaxCount)                                                                 \
        {                                                                                                                 \
            SET_ERROR_(ERR_CODE_IPARAM_VALUE_INVALID, ERR_MESSAGE_IPARAM_VALUE_INVALID,                                   \
                       "nBufferCount", nBufferCount, 1, MaxCount);                                                        \
            return false;                                                                                                 \
        }                                                                                                                 \
        if (methodFile.get()->DataArray.get() == nullptr)                                                                 \
        {                                                                                                                 \
            methodFile.get()->DataArray = std::make_shared<DataType[]>(nBufferCount);                                     \
        }                                                                                                                 \
        std::copy(pBuffer, pBuffer + nBufferCount, methodFile.get()->DataArray.get());                                    \
        methodFile.get()->CountArray = nBufferCount;                                                                      \
        if (nHandleType != METHOD_HANDLE)                                                                                 \
        {                                                                                                                 \
            std::shared_ptr<TOrgFile> &OrgFile = OrgFileMap[nHandle];                                                     \
            methodFile = OrgFile.get()->Method;                                                                           \
            OrgFile.get()->MethodLength = methodFile.get()->getTotalLength();                                             \
        }                                                                                                                 \
        return true;                                                                                                      \
    }                                                                                                                     \
    bool funcName(int64_t nHandle, int32_t nHandleType, const DataType *pBuffer, int32_t nBufferCount)                    \
    {                                                                                                                     \
        return funcName##_(nHandle, nHandleType, pBuffer, nBufferCount, false);                                           \
    }

// 使用宏定义各个函数
DEFINE_METHOD_GET_FUNCTION(getMethodEventList, TEventList, EventList, EventListCount, ERR_CODE_METHOD_HAS_NOT_EVENTLIST, ERR_MESSAGE_METHOD_HAS_NOT_EVENTLIST)
DEFINE_METHOD_SET_FUNCTION(setMethodEventList, TEventList, EventList, EventListCount, MAX_EVENTS)

DEFINE_METHOD_GET_FUNCTION(getMethodCompList, TCompList, CompList, CompListCount, ERR_CODE_METHOD_HAS_NOT_COMPLIST, ERR_MESSAGE_METHOD_HAS_NOT_COMPLIST)
DEFINE_METHOD_SET_FUNCTION(setMethodCompList, TCompList, CompList, CompListCount, MAX_COMPS)

DEFINE_METHOD_GET_FUNCTION(getMethodGroupList, TGroupList, GroupList, GroupListCount, ERR_CODE_METHOD_HAS_NOT_GROUPLIST, ERR_MESSAGE_METHOD_HAS_NOT_GROUPLIST)
DEFINE_METHOD_SET_FUNCTION(setMethodGroupList, TGroupList, GroupList, GroupListCount, MAX_GROUPS)

DEFINE_METHOD_GET_FUNCTION(getMethodSegmentList, TSegmentList, SegmentList, SegmentListCount, ERR_CODE_METHOD_HAS_NOT_SEGMENTLIST, ERR_MESSAGE_METHOD_HAS_NOT_SEGMENTLIST)
DEFINE_METHOD_SET_FUNCTION(setMethodSegmentList, TSegmentList, SegmentList, SegmentListCount, MAX_SEGMENTS)

DEFINE_METHOD_GET_FUNCTION(getMethodCalibList, TCalibList, CalibList, CalibListCount, ERR_CODE_METHOD_HAS_NOT_CALIBLIST, ERR_MESSAGE_METHOD_HAS_NOT_CALIBLIST)
DEFINE_METHOD_SET_FUNCTION(setMethodCalibList, TCalibList, CalibList, CalibListCount, MAX_CALIBRATIONS)

DEFINE_METHOD_GET_FUNCTION(getMethodCalibResult, TCalibResult, CalibResult, CalibResultCount, ERR_CODE_METHOD_HAS_NOT_CALIBRESULT, ERR_MESSAGE_METHOD_HAS_NOT_CALIBRESULT)
DEFINE_METHOD_SET_FUNCTION(setMethodCalibResult, TCalibResult, CalibResult, CalibResultCount, MAX_CALIB_RESULTS)